home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 13 The Compute Shader / VecAdd / VecAddCSApp.cpp < prev   
Encoding:
C/C++ Source or Header  |  2016-03-02  |  18.6 KB  |  561 lines

  1. //***************************************************************************************
  2. // VecAddCSApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "FrameResource.h"
  10.  
  11. using Microsoft::WRL::ComPtr;
  12. using namespace DirectX;
  13. using namespace DirectX::PackedVector;
  14.  
  15. #pragma comment(lib, "d3dcompiler.lib")
  16. #pragma comment(lib, "D3D12.lib")
  17.  
  18. const int gNumFrameResources = 3;
  19.  
  20. struct Data
  21. {
  22.     XMFLOAT3 v1;
  23.     XMFLOAT2 v2;
  24. };
  25.  
  26. // Lightweight structure stores parameters to draw a shape.  This will
  27. // vary from app-to-app.
  28. struct RenderItem
  29. {
  30.     RenderItem() = default;
  31.  
  32.     // World matrix of the shape that describes the object's local space
  33.     // relative to the world space, which defines the position, orientation,
  34.     // and scale of the object in the world.
  35.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  36.  
  37.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  38.  
  39.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  40.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  41.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  42.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  43.     int NumFramesDirty = gNumFrameResources;
  44.  
  45.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  46.     UINT ObjCBIndex = -1;
  47.  
  48.     Material* Mat = nullptr;
  49.     MeshGeometry* Geo = nullptr;
  50.  
  51.     // Primitive topology.
  52.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  53.  
  54.     // DrawIndexedInstanced parameters.
  55.     UINT IndexCount = 0;
  56.     UINT StartIndexLocation = 0;
  57.     int BaseVertexLocation = 0;
  58. };
  59.  
  60. enum class RenderLayer : int
  61. {
  62.     Opaque = 0,
  63.     Transparent,
  64.     AlphaTested,
  65.     Count
  66. };
  67.  
  68. class VecAddCSApp : public D3DApp
  69. {
  70. public:
  71.     VecAddCSApp(HINSTANCE hInstance);
  72.     VecAddCSApp(const VecAddCSApp& rhs) = delete;
  73.     VecAddCSApp& operator=(const VecAddCSApp& rhs) = delete;
  74.     ~VecAddCSApp();
  75.  
  76.     virtual bool Initialize()override;
  77.  
  78. private:
  79.     virtual void OnResize()override;
  80.     virtual void Update(const GameTimer& gt)override;
  81.     virtual void Draw(const GameTimer& gt)override;
  82.  
  83.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  84.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  85.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  86.  
  87.     void DoComputeWork();
  88.  
  89.     void BuildBuffers();
  90.     void BuildRootSignature();
  91.     void BuildDescriptorHeaps();
  92.     void BuildShadersAndInputLayout();
  93.     void BuildPSOs();
  94.     void BuildFrameResources();
  95.  
  96.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> GetStaticSamplers();
  97.  
  98. private:
  99.  
  100.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  101.     FrameResource* mCurrFrameResource = nullptr;
  102.     int mCurrFrameResourceIndex = 0;
  103.  
  104.     UINT mCbvSrvDescriptorSize = 0;
  105.  
  106.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  107.  
  108.     ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
  109.  
  110.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  111.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  112.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  113.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  114.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  115.  
  116.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  117.  
  118.     RenderItem* mWavesRitem = nullptr;
  119.  
  120.     // List of all the render items.
  121.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  122.  
  123.     // Render items divided by PSO.
  124.     std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
  125.  
  126.     const int NumDataElements = 32;
  127.  
  128.     ComPtr<ID3D12Resource> mInputBufferA = nullptr;
  129.     ComPtr<ID3D12Resource> mInputUploadBufferA = nullptr;
  130.     ComPtr<ID3D12Resource> mInputBufferB = nullptr;
  131.     ComPtr<ID3D12Resource> mInputUploadBufferB = nullptr;
  132.     ComPtr<ID3D12Resource> mOutputBuffer = nullptr;
  133.     ComPtr<ID3D12Resource> mReadBackBuffer = nullptr;
  134.  
  135.     PassConstants mMainPassCB;
  136.  
  137.     XMFLOAT3 mEyePos = { 0.0f, 0.0f, 0.0f };
  138.     XMFLOAT4X4 mView = MathHelper::Identity4x4();
  139.     XMFLOAT4X4 mProj = MathHelper::Identity4x4();
  140.  
  141.     float mTheta = 1.5f*XM_PI;
  142.     float mPhi = XM_PIDIV2 - 0.1f;
  143.     float mRadius = 50.0f;
  144.  
  145.     POINT mLastMousePos;
  146. };
  147.  
  148. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  149.     PSTR cmdLine, int showCmd)
  150. {
  151.     // Enable run-time memory check for debug builds.
  152. #if defined(DEBUG) | defined(_DEBUG)
  153.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  154. #endif
  155.  
  156.     try
  157.     {
  158.         VecAddCSApp theApp(hInstance);
  159.         if(!theApp.Initialize())
  160.             return 0;
  161.  
  162.         return theApp.Run();
  163.     }
  164.     catch(DxException& e)
  165.     {
  166.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  167.         return 0;
  168.     }
  169. }
  170.  
  171. VecAddCSApp::VecAddCSApp(HINSTANCE hInstance)
  172.     : D3DApp(hInstance)
  173. {
  174. }
  175.  
  176. VecAddCSApp::~VecAddCSApp()
  177. {
  178.     if(md3dDevice != nullptr)
  179.         FlushCommandQueue();
  180. }
  181.  
  182. bool VecAddCSApp::Initialize()
  183. {
  184.     if(!D3DApp::Initialize())
  185.         return false;
  186.  
  187.     // Reset the command list to prep for initialization commands.
  188.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  189.  
  190.     // Get the increment size of a descriptor in this heap type.  This is hardware specific, 
  191.     // so we have to query this information.
  192.     mCbvSrvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  193.  
  194.     BuildBuffers();
  195.     BuildRootSignature();
  196.     BuildDescriptorHeaps();
  197.     BuildShadersAndInputLayout();
  198.     BuildFrameResources();
  199.     BuildPSOs();
  200.  
  201.     // Execute the initialization commands.
  202.     ThrowIfFailed(mCommandList->Close());
  203.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  204.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  205.  
  206.     // Wait until initialization is complete.
  207.     FlushCommandQueue();
  208.  
  209.     DoComputeWork();
  210.  
  211.     return true;
  212. }
  213.  
  214. void VecAddCSApp::OnResize()
  215. {
  216.     D3DApp::OnResize();
  217.  
  218.     // The window resized, so update the aspect ratio and recompute the projection matrix.
  219.     XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  220.     XMStoreFloat4x4(&mProj, P);
  221. }
  222.  
  223. void VecAddCSApp::Update(const GameTimer& gt)
  224. {
  225.     // Cycle through the circular frame resource array.
  226.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  227.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  228.  
  229.     // Has the GPU finished processing the commands of the current frame resource?
  230.     // If not, wait until the GPU has completed commands up to this fence point.
  231.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  232.     {
  233.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  234.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  235.         WaitForSingleObject(eventHandle, INFINITE);
  236.         CloseHandle(eventHandle);
  237.     }
  238. }
  239.  
  240. void VecAddCSApp::Draw(const GameTimer& gt)
  241. {
  242.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  243.  
  244.     // Reuse the memory associated with command recording.
  245.     // We can only reset when the associated command lists have finished execution on the GPU.
  246.     ThrowIfFailed(cmdListAlloc->Reset());
  247.  
  248.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  249.     // Reusing the command list reuses memory.
  250.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  251.  
  252.     mCommandList->RSSetViewports(1, &mScreenViewport);
  253.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  254.  
  255.     // Indicate a state transition on the resource usage.
  256. //    mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  257. //        D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  258.  
  259.     // Clear the back buffer and depth buffer.
  260.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), (float*)&mMainPassCB.FogColor, 0, nullptr);
  261.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  262.  
  263.     // Specify the buffers we are going to render to.
  264.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  265.  
  266.  
  267.  
  268.     // Indicate a state transition on the resource usage.
  269.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  270.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  271.  
  272.     // Done recording commands.
  273.     ThrowIfFailed(mCommandList->Close());
  274.  
  275.     // Add the command list to the queue for execution.
  276.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  277.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  278.  
  279.     // Swap the back and front buffers
  280.     ThrowIfFailed(mSwapChain->Present(0, 0));
  281.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  282.  
  283.     // Advance the fence value to mark commands up to this fence point.
  284.     mCurrFrameResource->Fence = ++mCurrentFence;
  285.  
  286.     // Add an instruction to the command queue to set a new fence point. 
  287.     // Because we are on the GPU timeline, the new fence point won't be 
  288.     // set until the GPU finishes processing all the commands prior to this Signal().
  289.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  290. }
  291.  
  292. void VecAddCSApp::OnMouseDown(WPARAM btnState, int x, int y)
  293. {
  294.     mLastMousePos.x = x;
  295.     mLastMousePos.y = y;
  296.  
  297.     SetCapture(mhMainWnd);
  298. }
  299.  
  300. void VecAddCSApp::OnMouseUp(WPARAM btnState, int x, int y)
  301. {
  302.     ReleaseCapture();
  303. }
  304.  
  305. void VecAddCSApp::OnMouseMove(WPARAM btnState, int x, int y)
  306. {
  307.     if((btnState & MK_LBUTTON) != 0)
  308.     {
  309.         // Make each pixel correspond to a quarter of a degree.
  310.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  311.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  312.  
  313.         // Update angles based on input to orbit camera around box.
  314.         mTheta += dx;
  315.         mPhi += dy;
  316.  
  317.         // Restrict the angle mPhi.
  318.         mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi - 0.1f);
  319.     }
  320.     else if((btnState & MK_RBUTTON) != 0)
  321.     {
  322.         // Make each pixel correspond to 0.2 unit in the scene.
  323.         float dx = 0.2f*static_cast<float>(x - mLastMousePos.x);
  324.         float dy = 0.2f*static_cast<float>(y - mLastMousePos.y);
  325.  
  326.         // Update the camera radius based on input.
  327.         mRadius += dx - dy;
  328.  
  329.         // Restrict the radius.
  330.         mRadius = MathHelper::Clamp(mRadius, 5.0f, 150.0f);
  331.     }
  332.  
  333.     mLastMousePos.x = x;
  334.     mLastMousePos.y = y;
  335. }
  336.  
  337. void VecAddCSApp::DoComputeWork()
  338. {
  339.     // Reuse the memory associated with command recording.
  340.     // We can only reset when the associated command lists have finished execution on the GPU.
  341.     ThrowIfFailed(mDirectCmdListAlloc->Reset());
  342.  
  343.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  344.     // Reusing the command list reuses memory.
  345.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), mPSOs["vecAdd"].Get()));
  346.  
  347.     mCommandList->SetComputeRootSignature(mRootSignature.Get());
  348.  
  349.     mCommandList->SetComputeRootShaderResourceView(0, mInputBufferA->GetGPUVirtualAddress());
  350.     mCommandList->SetComputeRootShaderResourceView(1, mInputBufferB->GetGPUVirtualAddress());
  351.     mCommandList->SetComputeRootUnorderedAccessView(2, mOutputBuffer->GetGPUVirtualAddress());
  352.  
  353.     mCommandList->Dispatch(1, 1, 1);
  354.  
  355.     // Schedule to copy the data to the default buffer to the readback buffer.
  356.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mOutputBuffer.Get(),
  357.         D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE));
  358.  
  359.     mCommandList->CopyResource(mReadBackBuffer.Get(), mOutputBuffer.Get());
  360.  
  361.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mOutputBuffer.Get(),
  362.         D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COMMON));
  363.  
  364.     // Done recording commands.
  365.     ThrowIfFailed(mCommandList->Close());
  366.  
  367.     // Add the command list to the queue for execution.
  368.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  369.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  370.  
  371.     // Wait for the work to finish.
  372.     FlushCommandQueue();
  373.  
  374.     // Map the data so we can read it on CPU.
  375.     Data* mappedData = nullptr;
  376.     ThrowIfFailed(mReadBackBuffer->Map(0, nullptr, reinterpret_cast<void**>(&mappedData)));
  377.  
  378.     std::ofstream fout("results.txt");
  379.  
  380.     for(int i = 0; i < NumDataElements; ++i)
  381.     {
  382.         fout << "(" << mappedData[i].v1.x << ", " << mappedData[i].v1.y << ", " << mappedData[i].v1.z <<
  383.             ", " << mappedData[i].v2.x << ", " << mappedData[i].v2.y << ")" << std::endl;
  384.     }
  385.  
  386.     mReadBackBuffer->Unmap(0, nullptr);
  387. }
  388.  
  389. void VecAddCSApp::BuildBuffers()
  390. {
  391.     // Generate some data.
  392.     std::vector<Data> dataA(NumDataElements);
  393.     std::vector<Data> dataB(NumDataElements);
  394.     for(int i = 0; i < NumDataElements; ++i)
  395.     {
  396.         dataA[i].v1 = XMFLOAT3(i, i, i);
  397.         dataA[i].v2 = XMFLOAT2(i, 0);
  398.  
  399.         dataB[i].v1 = XMFLOAT3(-i, i, 0.0f);
  400.         dataB[i].v2 = XMFLOAT2(0, -i);
  401.     }
  402.  
  403.     UINT64 byteSize = dataA.size()*sizeof(Data);
  404.  
  405.     // Create some buffers to be used as SRVs.
  406.     mInputBufferA = d3dUtil::CreateDefaultBuffer(
  407.         md3dDevice.Get(),
  408.         mCommandList.Get(),
  409.         dataA.data(),
  410.         byteSize,
  411.         mInputUploadBufferA);
  412.  
  413.     mInputBufferB = d3dUtil::CreateDefaultBuffer(
  414.         md3dDevice.Get(),
  415.         mCommandList.Get(),
  416.         dataB.data(),
  417.         byteSize,
  418.         mInputUploadBufferB);
  419.  
  420.     // Create the buffer that will be a UAV.
  421.     ThrowIfFailed(md3dDevice->CreateCommittedResource(
  422.         &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  423.         D3D12_HEAP_FLAG_NONE,
  424.         &CD3DX12_RESOURCE_DESC::Buffer(byteSize, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS),
  425.         D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
  426.         nullptr,
  427.         IID_PPV_ARGS(&mOutputBuffer)));
  428.     
  429.     ThrowIfFailed(md3dDevice->CreateCommittedResource(
  430.         &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK),
  431.         D3D12_HEAP_FLAG_NONE,
  432.         &CD3DX12_RESOURCE_DESC::Buffer(byteSize),
  433.         D3D12_RESOURCE_STATE_COPY_DEST,
  434.         nullptr,
  435.         IID_PPV_ARGS(&mReadBackBuffer)));
  436. }
  437.  
  438. void VecAddCSApp::BuildRootSignature()
  439. {
  440.     // Root parameter can be a table, root descriptor or root constants.
  441.     CD3DX12_ROOT_PARAMETER slotRootParameter[3];
  442.  
  443.     // Perfomance TIP: Order from most frequent to least frequent.
  444.     slotRootParameter[0].InitAsShaderResourceView(0);
  445.     slotRootParameter[1].InitAsShaderResourceView(1);
  446.     slotRootParameter[2].InitAsUnorderedAccessView(0);
  447.  
  448.     // A root signature is an array of root parameters.
  449.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(3, slotRootParameter,
  450.         0, nullptr,
  451.         D3D12_ROOT_SIGNATURE_FLAG_NONE);
  452.  
  453.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  454.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  455.     ComPtr<ID3DBlob> errorBlob = nullptr;
  456.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  457.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  458.  
  459.     if(errorBlob != nullptr)
  460.     {
  461.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  462.     }
  463.     ThrowIfFailed(hr);
  464.  
  465.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  466.         0,
  467.         serializedRootSig->GetBufferPointer(),
  468.         serializedRootSig->GetBufferSize(),
  469.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  470. }
  471.  
  472. void VecAddCSApp::BuildDescriptorHeaps()
  473. {
  474.     
  475. }
  476.  
  477. void VecAddCSApp::BuildShadersAndInputLayout()
  478. {
  479.     mShaders["vecAddCS"] = d3dUtil::CompileShader(L"Shaders\\VecAdd.hlsl", nullptr, "CS", "cs_5_0");
  480. }
  481.  
  482. void VecAddCSApp::BuildPSOs()
  483. {
  484.     D3D12_COMPUTE_PIPELINE_STATE_DESC computePsoDesc = {};
  485.     computePsoDesc.pRootSignature = mRootSignature.Get();
  486.     computePsoDesc.CS =
  487.     {
  488.         reinterpret_cast<BYTE*>(mShaders["vecAddCS"]->GetBufferPointer()),
  489.         mShaders["vecAddCS"]->GetBufferSize()
  490.     };
  491.     computePsoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
  492.     ThrowIfFailed(md3dDevice->CreateComputePipelineState(&computePsoDesc, IID_PPV_ARGS(&mPSOs["vecAdd"])));
  493. }
  494.  
  495. void VecAddCSApp::BuildFrameResources()
  496. {
  497.     for(int i = 0; i < gNumFrameResources; ++i)
  498.     {
  499.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  500.             1));
  501.     }
  502. }
  503.  
  504. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> VecAddCSApp::GetStaticSamplers()
  505. {
  506.     // Applications usually only need a handful of samplers.  So just define them all up front
  507.     // and keep them available as part of the root signature.  
  508.  
  509.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  510.         0, // shaderRegister
  511.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  512.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  513.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  514.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  515.  
  516.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  517.         1, // shaderRegister
  518.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  519.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  520.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  521.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  522.  
  523.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  524.         2, // shaderRegister
  525.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  526.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  527.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  528.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  529.  
  530.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  531.         3, // shaderRegister
  532.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  533.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  534.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  535.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  536.  
  537.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  538.         4, // shaderRegister
  539.         D3D12_FILTER_ANISOTROPIC, // filter
  540.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  541.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  542.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  543.         0.0f,                             // mipLODBias
  544.         8);                               // maxAnisotropy
  545.  
  546.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  547.         5, // shaderRegister
  548.         D3D12_FILTER_ANISOTROPIC, // filter
  549.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  550.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  551.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  552.         0.0f,                              // mipLODBias
  553.         8);                                // maxAnisotropy
  554.  
  555.     return { 
  556.         pointWrap, pointClamp,
  557.         linearWrap, linearClamp, 
  558.         anisotropicWrap, anisotropicClamp };
  559. }
  560.  
  561.